/*
通信+串口测试程序
1. 读取MCU串口数据
2. 发送MCU串口数据
3. 发送激光串口数据
4. 读取激光串口数据
5. 读取红外串口数据
6. 发送红外串口数据
7. 读取可见光串口数据
8. 发送可见光串口数据
*/
#include "bsp_uart.h"
#include "bsp_pthread.h"
#include "gpioconfig.h"

/*全局声明*/
Update_t glb_data = {0};

int main(int argc, char **argv)
{
    /*sysfs init*/
    McuBspInit();
    LaserBspInit();
    /*Other init params ---------------- */
    pthread_t rx_mcu_thd;  
    pthread_t tx_mcu_thd;  
    pthread_t laser_thd;  
    pthread_t ir_thd;
    int ret = -1;


    /* init_mcu */
    ThreadDevContext* ctx_mcu = (ThreadDevContext*)malloc(sizeof(ThreadDevContext));
    memset(ctx_mcu, 0, sizeof(ThreadDevContext));
    /* init_laser */
    ThreadDevContext* ctx_laser = (ThreadDevContext*)malloc(sizeof(ThreadDevContext));
    memset(ctx_laser, 0, sizeof(ThreadDevContext));

    ThreadDevContext* ctx_icr_serial = (ThreadDevContext*)malloc(sizeof(ThreadDevContext));
    memset(ctx_icr_serial, 0, sizeof(ThreadDevContext));

    /*init glb mutex*/
    pthread_mutex_init(&glb_data.lock, NULL);
    /*init private mutex*/
    pthread_mutex_init(&ctx_mcu->lock, NULL);
    pthread_mutex_init(&ctx_laser->lock, NULL);
    pthread_mutex_init(&ctx_icr_serial->lock, NULL);
    /*init private cond*/
    pthread_cond_init(&ctx_mcu->cond, NULL);
    pthread_cond_init(&ctx_laser->cond, NULL);
    pthread_cond_init(&ctx_icr_serial->cond, NULL);

    /*thd status*/
    ctx_mcu->thdctlcmd = CMD_CTL_REGISTER;
    ctx_mcu->thdstop_flag = false;

    ctx_laser->thdctlcmd = CMD_CTL_REGISTER;
    ctx_laser->thdstop_flag = false;

    ctx_icr_serial->thdctlcmd = CMD_CTL_REGISTER;
    ctx_icr_serial->thdstop_flag = false;


    /* mcu uart init */
    ctx_mcu->args->uart = (Uart_t*)malloc(sizeof(Uart_t));
    memset(ctx_mcu->args->uart, 0, sizeof(Uart_t));
    ctx_mcu->args->uart = Context_init_uart("/dev/ttyS9",115200,8,1,'N');
    uart_init(ctx_mcu->args->uart, O_RDWR | O_NOCTTY | O_NONBLOCK);
    printf("Init_MCU_SERIAL:\n");
    uart_show_data(ctx_mcu->args->uart);

    /* laser uart init */
    ctx_laser->args->uart = (Uart_t*)malloc(sizeof(Uart_t));
    memset(ctx_laser->args->uart, 0, sizeof(Uart_t));
    ctx_laser->args->uart = Context_init_uart("/dev/ttyS0",38400,8,1,'N');
    uart_init(ctx_laser->args->uart, O_RDWR | O_NOCTTY | O_NONBLOCK);
    printf("Init_LASER_SERIAL:\n");
    uart_show_data(ctx_laser->args->uart);

    /* icr uart init */
    ctx_icr_serial->args->uart = (Uart_t*)malloc(sizeof(Uart_t));
    memset(ctx_icr_serial->args->uart, 0, sizeof(Uart_t));
    ctx_icr_serial->args->uart = Context_init_uart("/dev/ttyS0",115200,8,1,'N');
    uart_init(ctx_icr_serial->args->uart, O_RDWR | O_NOCTTY | O_NONBLOCK);
    printf("Init_ICR_SERIAL:\n");
    uart_show_data(ctx_icr_serial->args->uart);

    /* uart fds init */
    laser_fd   = &ctx_laser->args->uart->fd; //将laser_fd设置为当前线程的UART文件描述符
    icr_fd     = &ctx_laser->args->uart->fd; //将icr_fd设置为当前线程的UART文件描述符
    vis_fd  = &ctx_icr_serial->args->uart->fd; //将visble_fd设置为当前线程的UART文件描述符


    /*pthread create ---------------- */
    if (CMD_CTL_REGISTER == ctx_mcu->thdctlcmd)
    {
        /* code */
        ret = pthread_create(&rx_mcu_thd, NULL, thd_read_mcu, ctx_mcu);
        if (ret != 0) {
            goto err;
        }
        ret = pthread_create(&tx_mcu_thd, NULL, thd_send_mcu, ctx_mcu);
        if (ret != 0) {
            fprintf(stderr, "Failed to create encoder thread: %s\n", strerror(ret));
            goto err;
        }
    }
    if (CMD_CTL_REGISTER == ctx_laser->thdctlcmd)
    {
        /* code */
        ret = pthread_create(&laser_thd, NULL, Uarts_SelectFDs_thd, ctx_laser);
        if (ret != 0) {
            fprintf(stderr, "Failed to create encoder thread: %s\n", strerror(ret));

            return -1;
        }
    }
    printf("Read_MCU_thd thread started (ID: %lu)\n", (int64_t)rx_mcu_thd);
    printf("Send_MCU_thd thread started (ID: %lu)\n", (int64_t)tx_mcu_thd);
    printf("Send_laser_thd thread started (ID: %lu)\n", (int64_t)laser_thd);


    // 请求线程停止
    pthread_mutex_lock(&ctx_mcu->lock);
    ctx_mcu->thdstop_flag = true;
    pthread_cond_signal(&ctx_mcu->cond); // 通知线程
    pthread_mutex_unlock(&ctx_mcu->lock);

    pthread_mutex_lock(&ctx_laser->lock);
    ctx_laser->thdstop_flag = true;
    pthread_cond_signal(&ctx_laser->cond); // 通知线程
    pthread_mutex_unlock(&ctx_laser->lock);
    /* wait p_thd end*/ 
    ret = pthread_join(rx_mcu_thd, NULL);
    if (ret != 0) {
        fprintf(stderr, "Failed to join encoder thread: %s\n", strerror(ret));
    }
    ret = pthread_join(tx_mcu_thd, NULL);
    if (ret != 0) {
        fprintf(stderr, "Failed to join encoder thread: %s\n", strerror(ret));
    }
    ret = pthread_join(laser_thd, NULL);
    if (ret != 0) {
        fprintf(stderr, "Failed to join encoder thread: %s\n", strerror(ret));
    }
    /* free bsp resources */
    McuBspDeinit();
    /* free uart resources */
    if (ctx_mcu->args->uart != NULL)
    {
        free(ctx_mcu->args->uart);
        ctx_mcu->args->uart = NULL;
    }
    
    /* free uart resources */
    pthread_mutex_destroy(&ctx_mcu->lock);
    pthread_mutex_destroy(&ctx_laser->lock);

    pthread_cond_destroy(&ctx_mcu->cond);
    pthread_cond_destroy(&ctx_laser->cond);

    printf("Encoder thread completed\n");

err:
    /*err handle*/
    
    return -1;
}